上回介紹了如何使用建構式來建立原型,接著今天介紹使用  Object.create() 建立多層原型,先前在 T Shirt 例子有提到 , T Shirt 的原型是衣服,而衣服原型,仍然能有原型,這種多層原型就會使用 Object.create()  這個方法。

Object.create() 這個功能簡單來說就是,建立一個新的原型物件,而這個原型物件是沒有實體的,這邊使用範例來觀察
const Ryder = {
	name:'Ryder'
}
const student = Object.create(Ryder)
console.log(student) //{}
student.name // Ryder
雖然 student 實體仍是空物件,但我們使用 student.name  可以看到他會回傳 Ryder

這是因為 Object.create() 的功能,讓 student 的原型繼承  Ryder 的內容 ,可以點開 student  回傳的空物件,看看他 [[Prototype]] 的結構:

這樣便清楚 Object.create()  的功能其實就是能夠讓參數中的內容,成為目標的原型。
這邊複製之前的 TShirt 程式碼
function TShirt(color,material,size){
	this.color = color
	this.material = material
	this.size = size
}
TShirt.prototype.clothe = function() {
  console.log(`穿上 ${this.color} T Shit`);
}
const BlackTShit = new TShirt('black','棉','L')
目前是的原型鍊是
BlackTShit (子層) ⇒ TShirt (父層)
預期在 TShirt 上一層在新增一層 apparel  原型,也就是讓原型鍊變成
BlackTShit ⇒ TShirt ⇒ apparel (服飾)
接下來就是新增 apparel 原型,並使用剛剛介紹的 Object.create() , 讓 apparel 成為 TShirt 的原型,以下是範例:
// 新的一層原型
function apparel(type){
	this.type = type || 'T Shirt'
}
// 為新原型新增方法
apparel.prototype.mirror = function(){
 console.log(`我穿著 ${this.color} 的 ${this.type} `)
}
function TShirt(color,material,size){
	this.color = color
	this.material = material
	this.size = size
}
// 使用 Object.create 讓 TShirt 原型繼承 apparel 原型
TShirt.prototype = Object.create(apparel.prototype)
TShirt.prototype.clothe = function() {
  console.log(`穿上 ${this.color} T Shit`);
}
const BlackTShit = new TShirt('black','棉','L')
在這段範例中要特別注意的是這一段:
TShirt.prototype = Object.create(apparel.prototype)
這邊是讓 TShirt 這個函式建構式的原型,繼承了 apparel 函式就建構式的原型。
在完成上面使用 Object.create() 串連原型後,接著試者使用 mirror() 以及 clothe() 方法。
BlackTShit.clothe() //穿上 black T Shit
BlackTShit.mirror() //我穿著 black 的 undefined
可以發現在 apparel  這一層原型新增的方法雖然成功了, mirror() 方法中的 type 屬性卻無法正確顯示,這是因為使用 Object.create() 讓 TShirt 繼承了 apparel  的原型,但卻沒有繼承 apparel 的『建構函式』。
這時候需要在 TShirt  建構函式中使用 call() 方法,來讓 TShirt 中的 this 綁定到 apparel 上,而這段其實就是將兩個 建構函式 串接起來,並在傳入 'T Shirt' 字串當作 apparel 的 type 參數。
function apparel(type){
  this.type = type || '帽 T'
}
apparel.prototype.mirror = function(){
  console.log(`我穿著 ${this.color} 的 ${this.type} `)
}
function TShirt(color,material,size){
  apparel.call(this, 'T Shirt')
  this.color = color
  this.material = material
  this.size = size
}
TShirt.prototype = Object.create(apparel.prototype)
TShirt.prototype.constructor = TShirt
TShirt.prototype.clothe = function() {
  console.log(`穿上 ${this.color} T Shit`);
}
const BlackTShit = new TShirt('black','棉','L')
BlackTShit.mirror()
BlackTShit.clothe()
這樣在 console 打上  BlackTShit 便會看到,來自 TShirt 原型 、apparel 原型上的完整屬性以及內容了。
最後這邊看起來程式碼已經相當的完整了,但是如果要讓原型鍊完整的話,其實還必須在 Object.create() 底下加上 TShirt.prototype.constructor = TShirt ,這是因為在 Object.create() 設定時就會將原本 TShirt  原型中的內容在加回來。
function apparel(type){
	this.type = type || '帽 T'
}
// 為新原型新增方法
apparel.prototype.mirror = function(){
 console.log(`我穿著 ${this.color} 的 ${this.type} `)
}
function TShirt(color,material,size){
	apparel.call(this, 'T Shirt')
  this.color = color
	this.material = material
	this.size = size
}
// 透過 Object.create() 為 TShirt  
TShirt.prototype = Object.create(apparel.prototype)
TShirt.prototype.constructor = TShirt
TShirt.prototype.clothe = function() {
  console.log(`穿上 ${this.color} T Shit`);
}
const BlackTShit = new TShirt('black','棉','L')
BlackTShit.mirror()
BlackTShit.clothe()
這樣就是完整的讓原型繼承原型的方法了。